package com.echat.messagesender.sender.config;

import com.echat.commonlib.exception.exc.BussinessException;
import com.echat.messagesender.sender.email.EmailSender;
import com.echat.messagesender.sender.email.EmailSenderManager;
import com.echat.messagesender.sender.email.bean.EmailConfig;
import com.echat.messagesender.sender.email.bean.enumclass.EmailServerName;
import com.echat.messagesender.sender.email.impl.AliEmailSender;
import com.echat.messagesender.sender.email.impl.CommonsEmailSender;
import com.echat.messagesender.sender.email.impl.SendCloudEmailSender;
import com.echat.messagesender.sender.exception.EchatEmailException;
import com.echat.messagesender.sender.mapper.EmailProfileMapper;
import com.echat.messagesender.sender.mapper.PlatformAccountMapper;
import com.echat.messagesender.sender.mapper.PlatformMapper;
import com.echat.messagesender.sender.model.Platform;
import com.echat.messagesender.sender.model.PlatformAccount;
import com.echat.messagesender.sender.util.JsonUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * Created by chenmohan on 2018/09/06
 *
 * @description
 */
@Configuration
public class EmailSenderConfig {

    @Autowired
    EmailProfileMapper emailProfileMapper;

    @Autowired
    PlatformMapper platformMapper;

    @Bean
    public EmailSenderManager emailSenderManager() {
        //获取配置KV键值对 , key为 数据库中表"email_platform_profile"的 platform_id +"-"+tag , value是 profile_key和profile_value的键值对Map

        Map<Long, Map<String, String>> profileMap = emailProfileMapper.selectAll().parallelStream()
                .collect(Collectors.groupingBy(
                        e -> e.getPlatformAccountId(),
                        Collectors.toMap(e -> e.getKey(), e -> e.getValue()
                        )));

        //查数据库初始化EmailSender
        List<EmailConfig> emailConfigList = profileMap
                .entrySet().parallelStream().collect(Collectors.toMap(e -> e.getKey(), e -> {
                    EmailConfig config = (EmailConfig) JsonUtil.toBean(e.getValue(), EmailConfig.class);
                    config.setPlatformAccountId(e.getKey());
                    return config;
                }))     //按照配置sort排序，sort越大，越靠前
                .entrySet().parallelStream().map(e -> e.getValue()).sorted((o1, o2) -> o2.getSort() - o1.getSort()).collect(Collectors.toList());

        List<EmailSender> emailSenderList = emailConfigList.stream().map(e -> instanceEmailSender(e)).collect(Collectors.toList());
        Map<Long, EmailSender> emailSenderMap = emailSenderList.parallelStream().collect(Collectors.toMap(e -> e.getPlatformAccountId(), e -> e));
        EmailSenderManager emailSenderManager = new EmailSenderManager();
        emailSenderManager.setEmailSenderList(emailSenderList);
        emailSenderManager.setEmailSenderMap(emailSenderMap);
        return emailSenderManager;
    }

    /**
     * 创建sender实例
     * @param config
     * @return
     */
    private EmailSender instanceEmailSender(EmailConfig config) {
        if (config.getPlatformAccountId() == null) {
            throw new BussinessException("每个<config>下必须配置有效的<server>标签!请检查配置");
        }
        Long platformAccountId = config.getPlatformAccountId();
        Platform platform = platformMapper.selectByPlatformAccountId(platformAccountId);
        if (platform == null) {
            throw new EchatEmailException("platformAccountId = " + platformAccountId + " 的平台账号不存在!");
        }
        EmailServerName emailServerName = EmailServerName.get(platform.getId());
        config.setPlatformName(platform.getPlatformName());
        switch (emailServerName) {
            case AliCloud:
                return new AliEmailSender(config);
            case SendCloud:
                return new SendCloudEmailSender(config);
            case Apache:
                return new CommonsEmailSender(config);
        }
        return null;
    }
}
